package com.lap.generator.application;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import com.lap.generator.application.assembler.CodeGeneratorAssembler;
import com.lap.generator.config.ConfigLoader;
import com.lap.generator.config.EnvConfig;
import com.lap.generator.domain.CoreFile;
import com.lap.generator.domain.repository.FileWriter;
import com.lap.generator.domain.template.CodeGenContext;
import com.lap.generator.domain.template.CodeTemplate;
import com.lap.generator.domain.valueobject.CodeType;
import com.lap.generator.infrastructure.persistence.FileWriteImpl;
import com.lap.generator.infrastructure.query.DataSourceFactory;
import com.lap.generator.infrastructure.query.MetadataDialectFactory;
import com.lap.generator.infrastructure.query.meta.TableMeta;
import com.lap.generator.infrastructure.query.strategy.MetadataDialect;


@SuppressWarnings({"rawtypes", "unchecked"})
public class CodeGenerator {

  public void generate() throws SQLException {
    EnvConfig config = ConfigLoader.load();
    Connection connection = DataSourceFactory.resolver(config.getJdbcInfo());

    MetadataDialect dialect = MetadataDialectFactory.resolve(config.getJdbcInfo());
    List<TableMeta> tableMetaList =
        dialect.readTableMeta(connection, config.getJdbcInfo().getTable().getIncludes());

    List<CoreFile> result = getCoreFiles(tableMetaList, config);
    CoreFile message = getMessages(tableMetaList, config);
    result.add(message);

    FileWriter fileWriter = new FileWriteImpl();
    fileWriter.write(result);
  }

  private List<CoreFile> getCoreFiles(List<TableMeta> tableMetaList, EnvConfig config) {
    List<CodeType> list =
        List.of(CodeType.APP_SERVICE, CodeType.DRIVEN, CodeType.DOMAIN_MODEL, CodeType.DRIVING);

    List<CoreFile> result = new ArrayList<>();
    list.forEach(item -> tableMetaList.forEach(tableMeta -> {
      CodeGenContext context = new CodeGenContext(tableMeta, config);
      List<CodeTemplate> generators = CodeGeneratorAssembler.getGenerator(item);
      generators.forEach(generator -> result.addAll(generator.generate(context)));
    }));
    return result;
  }

  private CoreFile getMessages(List<TableMeta> tableMetaList, EnvConfig config) {
    List<CodeType> list = List.of(CodeType.MESSAGE);
    StringBuilder result = new StringBuilder();
    list.forEach(item -> tableMetaList.forEach(tableMeta -> {
      CodeGenContext context = new CodeGenContext(tableMeta, config);
      List<CodeTemplate> generators = CodeGeneratorAssembler.getGenerator(item);
      generators.forEach(generator -> {
        List<String> m = generator.generate(context);
        result.append("\n").append("##########").append("\n");
        result.append("#").append(tableMeta.getTableComment());
        result.append("\n").append("##########").append("\n");
        result.append(m.stream().collect(Collectors.joining("\n")));
      });
    }));

    return CoreFile.builder().path(".").fileName("message.properties").content(result.toString())
        .build();
  }
}
